package simpleGeom;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;

import marchingCubes.IsMCVertex;
import marchingCubes.MCube;


public class VoxelStreamFloat {
	String path;
	Box3D bounds;
	float dim;
	int nX;
	int nY;
	int nZ;
	public float x1,y1,z1;
	
	public Grid3DFloat grid;
	int startI;// current lowest Z index
	int nBuffer = 10;
	
	public VoxelStreamFloat(String path){
		this.path=path;
	}
	
	public VoxelStreamFloat(String path,float dim, float sX,float sY,float sZ,int nX,int nY,int nZ){
		this.path=path;
		this.dim=dim;
		this.nX=nX;
		this.nY=nY;
		this.nZ=nZ;
		bounds=new Box3D(sX,sY,sZ,nX*dim,nY*dim,nZ*dim);
		
	}
	
	public void initBuffer(int nBuffer){
		this.nBuffer=nBuffer;
		grid=new Grid3DFloat(nX,nBuffer,nZ);
		grid.dim=dim;
		System.out.println("init Buffer: "+nBuffer+" l: "+(nX*nZ));
	}
	public void initAllFiles(float initValue){
		initBuffer(1);
		Arrays.fill(grid.values,initValue);
		for (int i=0;i<nY;i++){
		writeFloatArrayY(this.getPath(i), 0);
		}
	}
	
	
	public void saveAllValues() {
		for (int i = 0; i < nBuffer; i++) {
			int cI = startI + i;
			if (cI>=0&&cI<nY){
				if (i%10==0){
					System.out.println("arraySaved");
				}
				writeFloatArrayY(this.getPath(cI), i);
			}
		}
		System.out.println("all Saved");
	}
	public void saveBuffer(int i){
		grid.saveValues(this.getPathBuffer(i));
	}
	public void loadBuffer(int i){
		grid.loadValues(this.getPathBuffer(i),grid.values);
	}
	public void loadAllValues() {
		for (int i = 0; i < nBuffer; i++) {
			//System.out.println("load i"+i);
			int cI = startI + i;
			if (cI>=0&&cI<nY){
				//System.out.println("cI"+cI)
				readFloatArrayY(this.getPath(cI), i);
			}
		}
	}
	
	
	public  void writeFloatArrayY(String fileName,int cY) {
		try {
			FileOutputStream fos3 = new FileOutputStream(fileName);
			DataOutputStream dos3 = new DataOutputStream(new BufferedOutputStream(fos3));
			int n = 0;
			int i;
			for (int x=0;x<nX;x++) {
				for (int z=0;z<nZ;z++) {
					dos3.writeFloat(grid.get(x, cY, z));
				}
			}
			dos3.flush();
			dos3.close();
			fos3.flush();
			fos3.close();
		}
		catch (FileNotFoundException ex) {
			System.out.println("FileNotFoundException : " + ex);
		} catch (IOException ioe) {
		}
	}
	public  void readFloatArrayY(String fileName,int cY){
		FileInputStream fin;
		try {
			fin = new FileInputStream(fileName);
			BufferedInputStream bin = new BufferedInputStream(fin);
			DataInputStream din = new DataInputStream(bin);
			for (int x=0;x<nX;x++) {
				for (int z=0;z<nZ;z++) {
			    try {
			    	int index=0;
			    	grid.set(x,cY,z, din.readFloat());
			    	
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			}
			din.close();
			bin.close();
			fin.close();
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}


	public float getValue(int x, int y, int z) {
		return grid.get(x, y-startI, z);
	}

	public void setValue(int x, int y, int z, float value) {
		grid.set(x, y-startI, z, value);
		
	}

	

	public String getPath(int i) {
		return path + "/" + (i +10000)+ ".dat";
	}
	public String getPathBuffer(int i) {
		return path + "/" + (i +10000)+"_"+ (i+nBuffer +10000)+ ".dat";
	}
	
	/*public void saveValues(float[] source, int targetI) {
		try {
			FileWriter fw = new FileWriter(getPath(targetI));
			
			BufferedWriter bw = new BufferedWriter(fw);
			int endI = source.length - 1;
			for (int i = 0; i < endI; i++) {
				bw.write("" + source[i]);
				bw.newLine();
			}
			bw.write("" + source[source.length - 1]);
			bw.flush();
			bw.close();
			fw.close();
			// fileOutputStream.close();
		} catch (Exception e) {
			
			System.err.println("error writing file: "+e);
		}
	}*/
	class Cell implements IsMCVertex {
		short x, y, z;
		float d = Float.MAX_VALUE;
		int id;
		MCube cube;
		Cell(int x, int y, int z) {
			this.x = (short) x;
			this.y = (short) y;
			this.z = (short) z;
		}

		public int getXK() {
			return x;
		}

		public int getYK() {
			return y;
		}

		public int getZK() {
			return z;
		}

		@Override
		public float getX() {
			// TODO Auto-generated method stub
			// return nX%3;
			//x * dim + bounds.x1
			return x ;
			// return x;
		}

		@Override
		public float getY() {
			// TODO Auto-generated method stub
			return y ;
			// return y;
		}

		public float getZ() {
			// TODO Auto-generated method stub
			return z ;
			// return z;
		}

		public float getValue() {
			return d;
		}

		public void setValue(float value) {
			this.d = value;
		}

		@Override
		public void setPosition(float x, float y, float z) {
			// TODO Auto-generated method stub

		}

		@Override
		public void setPosition(float x, float y) {
			// TODO Auto-generated method stub

		}

		@Override
		public int getId() {
			// TODO Auto-generated method stub
			return 0;
		}

		@Override
		public void setId(int i) {
			// TODO Auto-generated method stub

		}

		@Override
		public MCube getCube() {
			return cube;
		}

		@Override
		public void setCube(MCube cube) {
			// TODO Auto-generated method stub
			this.cube=cube;
		}

		@Override
		public void setZ(float z) {
			// TODO Auto-generated method stub

		}

		@Override
		public void setX(float x) {
			// TODO Auto-generated method stub

		}

		@Override
		public void setY(float Y) {
			// TODO Auto-generated method stub

		}

	}

}
